home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / NCSA / tn3270 2.3d26 source / tn3270 / writesf.c < prev    next >
Text File  |  1991-05-23  |  43KB  |  1,619 lines

  1. /*
  2.  *  tn3270 for the Macintosh Source Code
  3.  *  Brown University Computing and Information Services
  4.  *  Version 2.3d21, January 17, 1991
  5.  *  Copyright (c) 1988, 1989, 1990, 1991 by Brown University and by
  6.  *  Peter John DiCamillo.
  7.  *
  8.  *  Permission is granted to any individual or institution to use, copy,
  9.  *  or redistribute the binary version of this software and its
  10.  *  documentation provided this notice and the copyright notices are
  11.  *  retained.  Permission is granted to any individual or non-profit
  12.  *  institution to use, copy, modify, or redistribute the source files
  13.  *  of this software provided this notice and the copyright notices are
  14.  *  retained.  This software may not be distributed for profit, either
  15.  *  in original form or in derivative works, nor can the source be
  16.  *  distributed to other than an individual or a non-profit institution.
  17.  *  Any  individual or group interested in seeing and/or using these
  18.  *  source files but who are prevented from doing so by the above
  19.  *  constraints should contact Don Wolfe, Assistant Vice-President for
  20.  *  Computer Systems at Brown University, (401) 863-7250, for possible
  21.  *  software licensing of the source developed at Brown.
  22.  *
  23.  *  Brown University and Peter John DiCamillo make no representations
  24.  *  about the suitability of this software for any purpose.
  25.  *
  26.  *  BROWN UNIVERSITY AND PETER JOHN DICAMILLO GIVE NO WARRANTY, EITHER
  27.  *  EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION PROVIDED,
  28.  *  INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY AND
  29.  *  WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
  30.  *
  31.  */
  32.  
  33. /* Code in this file supports WSF functions: Query Reply,
  34.    normal 3270 data (calls writetm), file transfer (calls
  35.    vmxfer), and 3179 graphics.                                */
  36.  
  37. /* Reference manuals for graphics support:
  38.    IBM 3179 G Color Graphics Display Station Description,
  39.    GA18-2261
  40.    Reference Information for Picture Interchange Format,
  41.    SC33-0244  (part of IBM 3270 PC/G or PC/GX library)    
  42.  
  43.    General 3270 data stream information:
  44.    IBM 3270 Information Display System Data Stream
  45.    Programmer's Reference, GA23-0059 (revision -3 includes
  46.    some 3179 information)                                    */
  47.  
  48. /* Graphics has been tested using SAS version 5.16 with
  49.    device names of IBM3179 (SAS built-in support) and
  50.    GDDMPCGX (SAS calling GDDM Release 4).  Test plots include
  51.    the output from the GTESTIT procedure, the "cowboy hat"
  52.    sample, and the BITNET topology maps.                    */
  53.  
  54. #define __SEG__ 3270wsf
  55. #include "maclib.h"
  56. #include "termdef.h"
  57. #include "globals.h"
  58.  
  59. #define    IAC    255        /* interpret as command: */
  60. #define EOR 239     /* end of record (transparent mode) */
  61.  
  62. #define adMax 37    /* Color QuickDraw arithmetic drawing max mode */
  63. #define adMin 39    /* Color QuickDraw arithmetic drawing min mode */
  64.  
  65.                             /* MacDraw PicComment codes we use */
  66. #define picDwgBeg        130
  67. #define picDwgEnd        131
  68. #define picGrpBeg        140
  69. #define picGrpEnd        141
  70.                             /* LaserWriter PicComment codes we use */
  71. #define SetLineWidth    182
  72.  
  73. extern PaletteHandle myPalette;
  74. extern struct Point sfppoint;
  75. extern short vpixsize, hpixsize;
  76. extern Rect textRect;
  77.  
  78.  /* for file xfer */
  79. extern unsigned char * rbuf;    /* read buffer */
  80. extern unsigned char * sbuf;    /* send buffer */    
  81. extern short rlen;                /* read length */
  82. extern short slen;                /* send length */
  83.  
  84. extern RGBColor realblack, realwhite;
  85.  
  86. extern char newserver;            /* server supports new protocol */
  87. extern char pendalign;            /* pending bitmap alignment call */
  88. extern char skipnewmode;        /* cause writetm to skip call to newmode */
  89.  
  90. /* Code labelled "temp" is included to allow writing debugging data for
  91.    graphics support to a file.  Writing to the file is suppressed unless
  92.    "cs.dblevel" has been set by the main program.                            */
  93.  
  94. /*temp*/
  95. #include "stdio.h"
  96. static struct {
  97.     unsigned char wsf_op;
  98.     unsigned char wsf_gr;
  99.     unsigned char grf_op;
  100.     } wsfdbg;
  101.  
  102. short pleft, cleft;            /* byte counts for segment processing */
  103.  
  104.                             /* default settings (changed by Set Current Defaults) */
  105. unsigned char dfltcolor = 4;                /* default color =  green */
  106. unsigned char dfltlw = 1;                    /* default line width = 1 pixel */
  107. unsigned char dfltlt = 7;                    /* default line type = solid */
  108. unsigned char dfltmarker = 0xb5;            /* default marker = diamond */
  109. unsigned char dfltmix = 2;                    /* default mix mode */
  110. Pattern dfltpat = {0xff, 0xff, 0xff, 0xff,    /* default area pattern */
  111.                    0xff, 0xff, 0xff, 0xff};
  112.  
  113.                              /* current settings which must be global */
  114. unsigned char linew = 1;                    /* current line width */
  115. unsigned char linet = 7;                    /* current line type */
  116. short copymode = srcCopy;    /* current mode for CopyBits */
  117.  
  118.                             /* variables for creating PICT file */
  119. char pictopen = 0;                /* true when PICT file is open */
  120. char pict_fName[64] = {0};        /* name of open PICT file */
  121. short pictvref;                    /* volume reference for open PICT file */
  122. short pictfref;                    /* file reference for open PICT file */
  123. PicHandle picthandle;            /* handle for saved picture */
  124. long pictcount;                    /* size of picture */
  125. pascal void    myStdPutPic();        /* subroutine for writing file */
  126. OSErr picterr;                    /* error (if any) during writing */
  127. CQDProcs myProcs;                /* proc pointers for changing */
  128. Handle theWidth;                /* Handle for SetLineWidth */
  129. short xmin, xmax, ymin, ymax;    /* variables to define rectangle */
  130.  
  131. char area_active = 0;        /* flag to indicate area is active */
  132. char image_active = 0;        /* flag to indicate image data is active */
  133.  
  134. writesf(cmd, len, init)        /* write structured field */
  135. unsigned char * cmd;            /* command, starting with WSF op-code */
  136. short len;                        /* command length */
  137. char init;                        /* false = data continued from last call */
  138. {
  139. short currlen, curroff, fieldlen;
  140. unsigned char fieldid;
  141. char readflg;
  142.  
  143. if (!init) return;            /* currently, must get all data in one call */
  144. if (len < 1) return;
  145.  
  146. currlen = len - 1;            /* skip over wsf op-code */
  147. curroff = 1;
  148. while (currlen >= 3) {
  149.     fieldlen = cmd[curroff+1] + (cmd[curroff] << 8);
  150.     if (fieldlen == 0) fieldlen = currlen;
  151.     fieldid = cmd[curroff+2];
  152.     readflg = 0;
  153.     intwsf(fieldid, fieldlen, cmd+curroff, &readflg);
  154.     if (readflg) break;        /* command was a read of some sort */
  155.     curroff += fieldlen;
  156.     currlen -= fieldlen;
  157.     }
  158. }
  159.  
  160. intwsf(id, len, data, rdflag)    /* interpret one wsf field */
  161. unsigned char id;                    /* wsf field type code */
  162. short len;                            /* length of data */
  163. unsigned char * data;                /* data, starting with 2-byte length */
  164. char * rdflag;                        /* return 1 if read which generates response */
  165. {
  166. char sess_ext3270;
  167.  
  168. if (apiopen) {
  169.     sess_ext3270 = (apiopenreq.nowsf == 0);
  170.     }
  171. else {
  172.     sess_ext3270 = cs.ext3270;
  173.     }
  174.  
  175. /* temp */
  176. wsfdbg.wsf_op = id;
  177. wsfdbg.wsf_gr = wsfdbg.grf_op = 0;
  178.  
  179. switch(id) {
  180.  
  181.     case 0x01:                        /* read partition */
  182.                 if (len < 5) break;
  183.                 if ((data[4] == 0x02) || (data[4] == 0x03))
  184.                     if (data[3] == 0xff) 
  185.                         wsfrpq(len, data, newserver && (sess_ext3270 == 0));
  186.                 (*rdflag) = 1;
  187.                 break;
  188.  
  189.     case 0x03:                        /* erase/reset */
  190.                 if (data[3] & 0x80) {
  191.                     ewamode = 1;            /* establish alternate screen size */
  192.                     }
  193.                 else {
  194.                     ewamode = 0;            /* establish default screen size */
  195.                     }
  196.                 newmode(ewamode, 0);
  197.                 clrscn();                /* clear text */
  198.                 drawpict = 1;            /* force graphics clear */
  199.                 clrpict();                /* clear graphics */
  200.                 break;
  201.  
  202.     case 0x06:                        /* load PS set */
  203.                 /* ignore command to clear PS storage */
  204.                 if ((len == 7) && (data[3] & 0x40)) break;
  205.                 /* real PS load not supported */
  206.                 hexdump(data, len); /*temp*/
  207.                 break;
  208.  
  209.     case 0x09:                        /* set reply mode */
  210.                 /* not supported */
  211.                 hexdump(data, len); /*temp*/
  212.                 break;
  213.  
  214.     case 0x0c:                        /* create partition */
  215.                 /* not supported */
  216.                 hexdump(data, len); /*temp*/
  217.                 break;
  218.  
  219.     case 0x0f:                        /* graphic something */
  220.                 writegf(data, len);
  221.                 break;
  222.  
  223.     case 0x20:                        /* file transfer */
  224.                 /* special field type made up for Mac3270 */
  225.                 if (len < 4) break;    /* at least one data byte */
  226.                 rbuf = data+3;
  227.                 rlen = len-3;
  228.                 sbuf = readbuff+6;
  229.                 vmxfer();        /* process file transfer command */
  230.                 if (slen == 0) break;    /* send response, if generated */
  231.                 readbuff[0] = 0xd7;
  232.                 slen += 1;
  233.                 readbuff[5] = 0x88;
  234.                 rbsize = slen + 5;
  235.                 if (tcpflg) {
  236.                     readbuff[rbsize++] = IAC;
  237.                     readbuff[rbsize++] = EOR;
  238.                     }
  239.                 senddata(0xf6, rbsize-3, readbuff+3, 1);
  240.                 break;
  241.  
  242.     case 0x40:                        /* outbound 3270DS */
  243.                 if (len < 5) return;
  244.                 if (data[4] == 0x6f) {    /* EAU */
  245.                     funckey(10);        /* simulate CLEAR key pressed */
  246.                     rdaid = 0x60;
  247.                     break;
  248.                     }
  249.                 if ((data[3] == 0) && (data[4] == 0xf5)) {
  250.                     skipnewmode = 1;    /* EW with PID = 0 keeps mode */
  251.                     }
  252.                 ldvoff = 0;                /* normal 3270 data stream */
  253.                 writetm(data+4, len-4, 1);    /* update 3270 buffers */
  254.                 skipnewmode = 0;        /* reset special flag */
  255.                 invldscr();                /* display new contents */
  256.                 endwcc();                /* post-write WCC functions */
  257.                 break;
  258.     default:
  259.                 hexdump(data, len); /*temp*/
  260.                 break;
  261.     }
  262. }
  263.  
  264. wsfrpq(len, data, shortrsp)        /* Read Partition Query */
  265. short len;
  266. unsigned char * data;
  267. char shortrsp;
  268. {
  269. short i, j, listlen, reqtype, t, typecount, wsflen;
  270. static unsigned char long_wsftypes[] = {    /* all WSFR resources */    
  271.     0x86, 0x87, 0x85, 0x81, 0xa6, 0x88, 0x80, 0x84, 0x96, 0x99,
  272.     0xa1, 0xa8, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0x00};
  273. static unsigned char long_wsflist[] = {     /* 0x01 if in default list */
  274.     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,
  275.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  276. static unsigned char short_wsftypes[] = {    /* all WSFR resources */    
  277.     0x85, 0x81, 0xa6, 0x80, 0xa1, 0x00};
  278. static unsigned char short_wsflist[] = {     /* 0x01 if in default list */
  279.     0x01, 0x01, 0x01, 0x01, 0x00};
  280. unsigned char *wsftypes, *wsflist;
  281.  
  282. if (shortrsp) {
  283.     wsftypes = short_wsftypes;
  284.     wsflist = short_wsflist;
  285.     }
  286. else {
  287.     wsftypes = long_wsftypes;
  288.     wsflist = long_wsflist;
  289.     }
  290.  
  291. switch (data[4]) {
  292.     case 0x02:                /* Query */
  293.             listlen = 0;
  294.             reqtype = 1;
  295.             break;
  296.     case 0x03:                /* Query List */
  297.             if (len < 6) return;
  298.             listlen = len - 6;
  299.             reqtype = (data[5] & 0xc0) >> 6;
  300.             if (reqtype == 3) return;
  301.             break;
  302.     default:
  303.             return;
  304.     }
  305. typecount = strlen(wsftypes);
  306. wsflen = 0;
  307. for (i=0; i < typecount; i++) {        /* loop through all possible responses;
  308.                                        include in response those requested */
  309.     t = wsftypes[i];                /* t = resource number */
  310.     if (reqtype == 2) {        /* all types */
  311.         wsfadd(t, &wsflen, shortrsp);
  312.         if (t == 179) wsfadd(254, &wsflen, shortrsp); /* 2nd port response */
  313.         continue;
  314.         }
  315.     if ((reqtype == 1) && (wsflist[i] != 0)) {  /* default types wanted */
  316.         wsfadd(t, &wsflen, shortrsp);
  317.         if (t == 179) wsfadd(254, &wsflen, shortrsp); /* 2nd port response */
  318.         continue;
  319.         }
  320.     if (listlen == 0) continue;        /* listed types wanted */
  321.     for (j=0; j < listlen; j++)
  322.         if (data[j+6] == t) {
  323.             wsfadd(t, &wsflen, shortrsp);
  324.             if (t == 179) wsfadd(254, &wsflen, shortrsp); /* 2nd port response */
  325.             break;
  326.             }
  327.     }
  328.                             /* return null response if no other */
  329. if (wsflen == 0) wsfadd(255, &wsflen, shortrsp);    
  330. readbuff[0] = 0xd7;            /* send the response, similarly to read modified */
  331. wsflen += 1;
  332. readbuff[5] = 0x88;            /* AID code = 0x88 (structured field) */
  333. rbsize = wsflen + 5;
  334. if (tcpflg) {
  335.     readbuff[rbsize++] = IAC;
  336.     readbuff[rbsize++] = EOR;
  337.     }
  338. senddata(0xf6, rbsize-3, readbuff+3, 1);
  339. }
  340.  
  341. wsfadd(num, len, shortrsp)        /* add resource no. "num" to response */
  342. short num;
  343. short *len;
  344. char shortrsp;
  345. {
  346. unsigned char **rhandle;
  347. short rlen, rnum;
  348. void (*procptr)();
  349. void def_ua();
  350. void def_ip();
  351. unsigned char rscbuff[64];
  352.  
  353. rnum = num;        /* default resource is argument */
  354.  
  355. switch(num) {
  356.     case 129:    procptr = def_ua;        /* usable area */
  357.                 break;
  358.     case 166:    procptr = def_ip;        /* implicit partition */
  359.                 break;
  360.     default:    procptr = 0;
  361.                 break;
  362.     }
  363.  
  364. if (ses_altptsize == 12) {
  365.     switch(num) {
  366.         case 133:    rnum = 252;            /* character sets */
  367.                     break;
  368.         case 182:    rnum = 250;            /* graphic symbol sets */
  369.                     break;
  370.         default:    break;
  371.         }
  372.     }
  373.  
  374. if (colormac) if (num == 134) rnum = 245;
  375. if (shortrsp) if (num == 128) rnum = 244;
  376.  
  377. if (cs.simps) {                    /* include PS character set response */
  378.     if (rnum == 133) rnum = 251;
  379.     if (rnum == 252) rnum = 253;
  380.     }
  381.  
  382. rhandle = (unsigned char **)GetResource('WSFR', rnum);
  383. if (rhandle == 0) return;    /* should report error here */
  384. rlen = ((*rhandle)[0] << 8) + (*rhandle)[1];
  385.                     /* modify response which depends on screen format */
  386. if (procptr != 0) {
  387.     movmem((*rhandle), rscbuff, rlen);
  388.     (*procptr)(rscbuff, rlen);
  389.     tcpmovmem(rscbuff, readbuff+6+(*len), &rlen);
  390.     }
  391. else {
  392.     tcpmovmem((*rhandle), readbuff+6+(*len), &rlen);
  393.     }
  394. (*len) += rlen;
  395. }
  396.  
  397.                     /* modify usable area response for screen format */
  398. void def_ua(resptr, reslen)
  399. uareply *resptr;
  400. short reslen;
  401. {
  402. union {
  403.     unsigned short i;
  404.     unsigned char s[2];
  405.     } cvt;
  406.  
  407. resptr->w = 80;
  408. resptr->h = 24;
  409. switch (ses_dfltptsize) {
  410.     case 12:
  411.             resptr->aw = 7;
  412.             resptr->ah = 16;
  413.             break;
  414.     default:
  415.             resptr->aw = 6;
  416.             resptr->ah = 12;
  417.             break;
  418.     }
  419.  
  420. cvt.i = ses_altcols;
  421. movmem(cvt.s, resptr->waua, 2);
  422. cvt.i = ses_altrows;
  423. movmem(cvt.s, resptr->haua, 2);
  424. switch (ses_altptsize) {
  425.     case 12:
  426.             resptr->awaua = 7;
  427.             resptr->ahaua = 16;
  428.             break;
  429.     default:
  430.             resptr->awaua = 6;
  431.             resptr->ahaua = 12;
  432.             break;
  433.     }
  434. }
  435.     
  436.                     /* modify implicit partition response for screen format */
  437. void def_ip(resptr, reslen)
  438. ipreply *resptr;
  439. short reslen;
  440. {
  441. union {
  442.     unsigned short i;
  443.     unsigned char s[2];
  444.     } cvt;
  445.  
  446. cvt.i = 80;
  447. movmem(cvt.s, resptr->wd, 2);
  448. cvt.i = 24;
  449. movmem(cvt.s, resptr->hd, 2);
  450. cvt.i = ses_altcols;
  451. movmem(cvt.s, resptr->wa, 2);
  452. cvt.i = ses_altrows;
  453. movmem(cvt.s, resptr->ha, 2);
  454. switch (ses_dfltptsize) {
  455.     case 12:
  456.             cvt.i = 7;
  457.             movmem(cvt.s, resptr->wcd, 2);
  458.             cvt.i = 16;
  459.             movmem(cvt.s, resptr->hcd, 2);
  460.             break;
  461.     default:
  462.             cvt.i = 6;
  463.             movmem(cvt.s, resptr->wcd, 2);
  464.             cvt.i = 12;
  465.             movmem(cvt.s, resptr->hcd, 2);
  466.             break;
  467.     }
  468. switch (ses_altptsize) {
  469.     case 12:
  470.             cvt.i = 7;
  471.             movmem(cvt.s, resptr->wca, 2);
  472.             cvt.i = 16;
  473.             movmem(cvt.s, resptr->hca, 2);
  474.             break;
  475.     default:
  476.             cvt.i = 6;
  477.             movmem(cvt.s, resptr->wca, 2);
  478.             cvt.i = 12;
  479.             movmem(cvt.s, resptr->hca, 2);
  480.             break;
  481.     }
  482. }
  483.     
  484. writegf(data, len)        /* graphic data stream */
  485. unsigned char * data;
  486. short len;
  487. {
  488. short i;
  489.  
  490. wsfdbg.wsf_gr = data[3];        /*temp*/
  491.  
  492. switch(data[3]) {
  493.     case 0x0f:                            /* graphic data */
  494.                 /* not supported */        /* controls inbound graphics data */
  495.                 hexdump(data+7, len-7); /*temp*/
  496.                 break;
  497.     case 0x10:                            /* graphic picture */
  498.                 if (data[5] & 0x80) {
  499.                     pleft = 0;                /* if first, reset count */
  500.                     initpict();                /* maybe start of new picture */
  501.                     }
  502.                 if (len < 8) break;
  503.                 for (i=7; i < len; i++) grpparse(data[i]);
  504.                 if (data[5] & 0x40) showpict();    /* if last, show result */
  505.                 break;
  506.     case 0x11:                            /* graphic control */
  507.                 if (data[5] & 0x80) {
  508.                     cleft = 0;                /* if first, reset count */
  509.                     initpict();                /* maybe start of new picture */
  510.                     }
  511.                 if (len < 8) break;
  512.                 for (i=7; i < len; i++) grcparse(data[i]);
  513.                 if (data[5] & 0x40) showpict();    /* if last, show result */
  514.                 break;
  515.     case 0x1f:                            /* OEM data */
  516.                 /* not supported */
  517.                 hexdump(data+7, len-7); /*temp*/
  518.                 break;
  519.  
  520.     default:    hexdump(data+7, len-7);    /*temp*/
  521.                 break;
  522.     }
  523. }
  524.  
  525. grpparse(c)            /* interpret graphic picture data */
  526. unsigned char c;
  527. {
  528. static short ptemp1, pboff, pcount;
  529. static char pmode;
  530. static unsigned char pictbuff[257];
  531.  
  532. if (pleft == 0) {
  533.     pmode = pcount = 0;
  534.     pleft = 14;
  535.     }
  536.  
  537. switch (pmode) {
  538.     case 0:                    /* processing segment header */
  539.             if (pcount == 8) ptemp1 = c;
  540.             if (pcount == 9) pleft = (ptemp1 << 8) + c + 5;
  541.             if (pcount == 13) {
  542.                     pmode = 1;
  543.                     pcount = 0;
  544.                     }
  545.             else pcount++;
  546.             break;
  547.     case 1:                    /* processing order */
  548.             if (pcount == 0) {
  549.                 pboff = 0;
  550.                 pictbuff[pboff++] = c;
  551.                 if ((c==0x00) || (c==0x20) || (c==0xff)) {
  552.                     exdraw(pictbuff, pboff);
  553.                     pcount = 0;
  554.                     }
  555.                 else pcount++;
  556.                 break;
  557.                 }
  558.             pictbuff[pboff++] = c;
  559.             if (pcount == 1) {
  560.                 if (((pictbuff[0] <= 0x7f) &&
  561.                       ((pictbuff[0] & 0x0f) >= 8)) || (c == 0)) {
  562.                     exdraw(pictbuff, pboff);
  563.                     pcount = 0;
  564.                     }
  565.                 else {
  566.                     ptemp1 = c;        /* no. of operand bytes left */
  567.                     pcount++;
  568.                     }
  569.                 break;
  570.                 }
  571.             pcount++;
  572.             ptemp1--;
  573.             if (ptemp1 == 0) {
  574.                 exdraw(pictbuff, pboff);
  575.                 pcount = 0;
  576.                 }
  577.             break;
  578.     default:
  579.             break;
  580.     }
  581. pleft--;
  582. }
  583.  
  584.  
  585. exdraw(opdata, len)            /* process drawing order */
  586. unsigned char * opdata;
  587. short len;
  588. {
  589. static short xpos, ypos;
  590. short r, s;
  591. union {
  592.     short ipos;
  593.     char cpos[2];
  594.     } cvt;
  595. GrafPtr gp, dp;
  596. short newcolor;
  597. RGBColor rgbtemp;
  598. static unsigned char markchar = 0xb5;    /* current marker */
  599. static Pattern fillpat = {0xff, 0xff, 0xff, 0xff,    /* current area pattern */
  600.                              0xff, 0xff, 0xff, 0xff};
  601. static PolyHandle mypoly;
  602. static unsigned char aflags;
  603. static unsigned char markstr[2] = {1, 0};    /* one-byte Pascal string */
  604. static BitMap image_srcBits;
  605. static Rect image_srcRect, image_dstRect;
  606. static short image_rowcount;
  607. unsigned char imagebuff[258];
  608. unsigned char * imageptr;
  609. short imgoffset;
  610.  
  611. GetPort(&gp);
  612. if (PictPtr != 0) {
  613.     SetPort(PictPtr);
  614.     setgdev();
  615.     }
  616. else {
  617.     SetPort(myWindow);
  618.     }
  619. GetPort(&dp);
  620.  
  621. if (cs.dblevel == 3) {                /* dump all graphics if level 3 */
  622.     wsfdbg.grf_op = opdata[0];    /* temp */
  623.     hexdump(opdata, len);        /* temp */
  624.     }
  625.  
  626. switch(opdata[0]) {
  627.         case 0xa1:                    /* rel. line at current pos. */
  628.             r = opdata[1]/2;
  629.             s = 2;
  630.             MoveTo(sx(xpos), sy(ypos));
  631.             while (r > 0) {    
  632.                 xpos += (char)opdata[s++];
  633.                 ypos += (char)opdata[s++];
  634.                 myLineTo(sx(xpos), sy(ypos));
  635.                 r --;
  636.                 }
  637.             break;
  638.         case 0x21:                    /* set current position */
  639.             cvt.cpos[0] = opdata[2];
  640.             cvt.cpos[1] = opdata[3];
  641.             xpos = cvt.ipos;
  642.             cvt.cpos[0] = opdata[4];
  643.             cvt.cpos[1] = opdata[5];
  644.             ypos = cvt.ipos;
  645.             break;
  646.         case 0x83:                    /* char. string at curr. pos. */
  647.             MoveTo(sx(xpos), sy(ypos)-2);
  648.             myDrawString(opdata+1);
  649.             break;
  650.         case 0xc3:                    /* char. string at given pos. */
  651.             cvt.cpos[0] = opdata[2];
  652.             cvt.cpos[1] = opdata[3];
  653.             xpos = cvt.ipos;
  654.             cvt.cpos[0] = opdata[4];
  655.             cvt.cpos[1] = opdata[5];
  656.             ypos = cvt.ipos;
  657.             MoveTo(sx(xpos), sy(ypos));
  658.             opdata[5] = opdata[1] - 4;
  659.             if (opdata[5] < 0) opdata[5] = 0;
  660.             myDrawString(opdata+5);
  661.             break;
  662.         case 0x85:                    /* fillet at current position */
  663.                 /* see comment below for fillet at given position */
  664.         case 0x81:                    /* line at current position */
  665.             r = opdata[1]/4;
  666.             s = 2;
  667.             MoveTo(sx(xpos), sy(ypos));
  668.             while (r > 0) {    
  669.                 cvt.cpos[0] = opdata[s++];
  670.                 cvt.cpos[1] = opdata[s++];
  671.                 xpos = cvt.ipos;
  672.                 cvt.cpos[0] = opdata[s++];
  673.                 cvt.cpos[1] = opdata[s++];
  674.                 ypos = cvt.ipos;
  675.                 myLineTo(sx(xpos), sy(ypos));
  676.                 r --;
  677.                 }
  678.             break;
  679.         case 0xc5:                    /* fillet at given position */
  680.                 /* Too hard to do correctly for now, but at least    */
  681.                 /* draw the lines the curve should be tangent to,    */
  682.                 /* and update the current position.  Fillet has        */
  683.                 /* not been encountered in any test plots.            */
  684.         case 0xc1:                    /* line at given position */
  685.             cvt.cpos[0] = opdata[2];
  686.             cvt.cpos[1] = opdata[3];
  687.             xpos = cvt.ipos;
  688.             cvt.cpos[0] = opdata[4];
  689.             cvt.cpos[1] = opdata[5];
  690.             ypos = cvt.ipos;
  691.             MoveTo(sx(xpos), sy(ypos));
  692.             r = (opdata[1]-4)/4;
  693.             s = 6;
  694.             while (r > 0) {    
  695.                 cvt.cpos[0] = opdata[s++];
  696.                 cvt.cpos[1] = opdata[s++];
  697.                 xpos = cvt.ipos;
  698.                 cvt.cpos[0] = opdata[s++];
  699.                 cvt.cpos[1] = opdata[s++];
  700.                 ypos = cvt.ipos;
  701.                 myLineTo(sx(xpos), sy(ypos));
  702.                 r --;
  703.                 }
  704.             break;
  705.         case 0xe1:                    /* relative line at given pos. */
  706.             cvt.cpos[0] = opdata[2];
  707.             cvt.cpos[1] = opdata[3];
  708.             xpos = cvt.ipos;
  709.             cvt.cpos[0] = opdata[4];
  710.             cvt.cpos[1] = opdata[5];
  711.             ypos = cvt.ipos;
  712.             MoveTo(sx(xpos), sy(ypos));
  713.             r = (opdata[1]-4)/2;
  714.             s = 6;
  715.             while (r > 0) {    
  716.                 xpos += (char)opdata[s++];
  717.                 ypos += (char)opdata[s++];
  718.                 myLineTo(sx(xpos), sy(ypos));
  719.                 r --;
  720.                 }
  721.             break;
  722.         case 0xc7:                /* full arc at given position */
  723.                 /* Arcs are not supported yet, but at least move to    */
  724.                 /* the specified position.  Arc commands have not    */
  725.                 /* been encountered in any test plots.                */
  726.             cvt.cpos[0] = opdata[2];
  727.             cvt.cpos[1] = opdata[3];
  728.             xpos = cvt.ipos;
  729.             cvt.cpos[0] = opdata[4];
  730.             cvt.cpos[1] = opdata[5];
  731.             ypos = cvt.ipos;
  732.             break;
  733.         case 0x87:                /* full arc at current position */
  734.                 /* doesn't affect current position */
  735.         case 0x22:                /* set arc parameters */
  736.             break;
  737.         case 0x26:                /* set extended color */
  738.             setrgb(&newcolor, opdata[3]);
  739.             if (colormac) {
  740.                 GetEntryColor(myPalette, newcolor, &rgbtemp);
  741.                 RGBForeColor(&rgbtemp);        /* set foreground drawing color */
  742.                 }
  743.             else {
  744.                 if (newcolor == RGBblack) {
  745.                     ForeColor(whiteColor);
  746.                     }
  747.                 else {
  748.                     ForeColor(blackColor);
  749.                     }
  750.                 }
  751.             break;
  752.         case 0x0a:                /* set color */
  753.             setrgb(&newcolor, opdata[1]);
  754.             if (colormac) {
  755.                 GetEntryColor(myPalette, newcolor, &rgbtemp);
  756.                 RGBForeColor(&rgbtemp);        /* set foreground drawing color */
  757.                 }
  758.             else {
  759.                 if (newcolor == RGBblack) {
  760.                     ForeColor(whiteColor);
  761.                     }
  762.                 else {
  763.                     ForeColor(blackColor);
  764.                     }
  765.                 }
  766.             break;
  767.         case 0x68:                /* begin area */
  768.             mypoly = OpenPoly();    /* create new polygon */
  769.             aflags = opdata[1];        /* save flag bits */
  770.             area_active = 1;        /* remeber area is active */
  771.             break;
  772.         case 0x60:                /* end area */
  773.             if (area_active == 0) {    /* check for datastream error */
  774.                 break;
  775.                 }
  776.             ClosePoly();            /* done saving stuff */
  777.             PenPat(fillpat);        /* set fill pattern */
  778.             PaintPoly(mypoly);        /* draw it */
  779.             PenPat(qd.black);        /* restore default pattern */
  780.             if (aflags & 0x40) FramePoly(mypoly);  /* handle outline */
  781.             KillPoly(mypoly);        /* dispose of it */
  782.             area_active = 0;        /* reset active flag */
  783.             break;
  784.         case 0x28:                /* set pattern symbol (area fill pattern) */
  785.             setpat(fillpat, opdata[1]);
  786.             break;
  787.         case 0x29:                /* set marker symbol */
  788.             setmark(&markchar, opdata[1]);
  789.             break;
  790.         case 0xc2:                /* marker at given position */
  791.         case 0x82:                /* marker at current position */
  792.             r = opdata[1]/4;
  793.             s = 2;
  794.             while (r > 0) {    
  795.                 cvt.cpos[0] = opdata[s++];
  796.                 cvt.cpos[1] = opdata[s++];
  797.                 xpos = cvt.ipos;
  798.                 cvt.cpos[0] = opdata[s++];
  799.                 cvt.cpos[1] = opdata[s++];
  800.                 ypos = cvt.ipos;
  801.                 MoveTo(sx(xpos), sy(ypos)+4);
  802.                 markstr[1] = markchar;        /* make 1-character Pascal string */
  803.                 myDrawString(markstr);
  804.                 r --;
  805.                 }
  806.             break;
  807.         case 0x18:                /* set line type */
  808.             if (opdata[1] == 0) linet = dfltlt;
  809.             else linet = opdata[1];
  810.             break;
  811.         case 0x19:                /* set line width */
  812.             if (opdata[1] == 0) linew = dfltlw;
  813.             else linew = opdata[1];
  814.             break;
  815.         case 0xd1:                /* begin image */
  816.         case 0x91:                /* begin image at current position */
  817.             image_srcRect.top = 0;
  818.             image_srcRect.left = 0;
  819.             image_srcRect.bottom = 1;
  820.             if (opdata[0] == 0xd1) {
  821.                 /* ignore if not in the format we expect*/
  822.                 if (opdata[1] != 10) break;
  823.                 if (opdata[6] != 0) break;
  824.                 if (opdata[7] != 0) break;
  825.                 /* define upper left corner of bitmap */
  826.                 cvt.cpos[0] = opdata[2];
  827.                 cvt.cpos[1] = opdata[3];
  828.                 image_dstRect.left = sx(cvt.ipos);
  829.                 cvt.cpos[0] = opdata[4];
  830.                 cvt.cpos[1] = opdata[5];
  831.                 image_dstRect.top = sy(cvt.ipos);
  832.                 imgoffset = 8;
  833.                 }
  834.             else {
  835.                 /* ignore if not in the format we expect*/
  836.                 if (opdata[1] != 6) break;
  837.                 if (opdata[2] != 0) break;
  838.                 if (opdata[3] != 0) break;
  839.                 /* define upper left corner of bitmap */
  840.                 image_dstRect.left = sx(xpos);
  841.                 image_dstRect.top = sy(ypos);
  842.                 imgoffset = 4;
  843.                 }
  844.             image_dstRect.bottom = image_dstRect.top + 1;
  845.             /* convert width */
  846.             cvt.cpos[0] = opdata[imgoffset];
  847.             cvt.cpos[1] = opdata[imgoffset+1];
  848.             image_srcRect.right = cvt.ipos;
  849.             image_dstRect.right = image_dstRect.left + cvt.ipos;
  850.             image_srcBits.rowBytes = (cvt.ipos+7)/8;
  851.             if (image_srcBits.rowBytes%2) image_srcBits.rowBytes++;
  852.             /* convert height */
  853.             cvt.cpos[0] = opdata[imgoffset+2];
  854.             cvt.cpos[1] = opdata[imgoffset+3];
  855.             image_rowcount = cvt.ipos;
  856.             image_srcBits.bounds = image_srcRect;
  857.             if (pictopen) {
  858.                 if (image_dstRect.top < ymin) ymin = image_dstRect.top;
  859.                 if (image_dstRect.top > ymax) ymax = image_dstRect.top;
  860.                 if (image_dstRect.bottom < ymin) ymin = image_dstRect.bottom;
  861.                 if (image_dstRect.bottom > ymax) ymax = image_dstRect.bottom;
  862.                 if (image_dstRect.left < xmin) xmin = image_dstRect.left;
  863.                 if (image_dstRect.left > xmax) xmax = image_dstRect.left;
  864.                 if (image_dstRect.right < xmin) xmin = image_dstRect.right;
  865.                 if (image_dstRect.right > xmax) xmax = image_dstRect.right;
  866.                 }
  867.             image_active = 1;
  868.             break;
  869.         case 0x92:                /* image data */
  870.             if (image_active == 0) break;
  871.             if (image_rowcount == 0) break;
  872.             image_rowcount--;
  873.             imageptr = imagebuff;
  874.             if (((long)imageptr)%2) imageptr++;
  875.             memcpy(imageptr, opdata+2, opdata[1]);
  876.             image_srcBits.baseAddr = imageptr;
  877.             if (colormac) {
  878.                 GetBackColor(&rgbtemp);
  879.                 if (cs.invertbw) { 
  880.                     RGBBackColor(&realwhite);
  881.                     }
  882.                 else {
  883.                     RGBBackColor(&realblack);
  884.                     }
  885.                 CopyBits(&image_srcBits, &(dp->portBits),
  886.                     &image_srcRect, &image_dstRect, copymode, 0L);
  887.                 RGBBackColor(&rgbtemp);
  888.                 }
  889.             else {
  890.                 CopyBits(&image_srcBits, &(dp->portBits),
  891.                     &image_srcRect, &image_dstRect, copymode, 0L);
  892.                 }
  893.             image_dstRect.top++;
  894.             image_dstRect.bottom++;
  895.             break;
  896.         case 0x93:                /* end image */
  897.             if (image_active == 0) break;
  898.             image_active = 0;
  899.             break;
  900.         case 0x0c:                /* set foreground mix */
  901.             setmixmode(opdata[1]);
  902.             break;
  903.         /* The following are not easily implemented using QuickDraw; */
  904.         /* none of these appear to be needed for the test plots to     */
  905.         /* display correctly:                                           */
  906.         case 0x33:                /* set character cell */
  907.         case 0x34:                /* set character angle */
  908.         case 0x35:                /* set character shear */
  909.         case 0x38:                /* set character set */
  910.         case 0x3a:                /* set character direction */
  911.         case 0x37:                /* set marker cell */
  912.         case 0xff:                /* end of symbol definition */
  913.         /* The following are documented by IBM to be ignored in    files    */
  914.         /* imported into GGXA, and are unlikely to be used.  None of    */
  915.         /* of the test plots need them.                                    */
  916.         case 0x0d:                /* set background mix */
  917.             /* no-op for 3179 */
  918.         case 0x39:                /* set character precision */
  919.         case 0x3b:                /* set marker precision */
  920.         case 0x3c:                /* set marker set */
  921.         case 0x08:                /* set pattern set */
  922.         case 0x43:                /* set pick identifier */
  923.         case 0x04:                /* segment characteristics */
  924.         case 0x3e:                /* end prologue */
  925.         case 0x71:                /* end segment */
  926.         /* these do nothing by definition */
  927.         case 0x01:                /* comment */
  928.         case 0x00:                /* no-op */
  929.             break;
  930.         default:
  931.             if (cs.dblevel == 3) break;    /* for level 3, already dumped */
  932.             wsfdbg.grf_op = opdata[0];    /* temp */
  933.             hexdump(opdata, len);        /* temp */
  934.             break;
  935.         }
  936.  
  937. if (PictPtr != 0) resetgdev();
  938. SetPort(gp);
  939. }
  940.  
  941. grcparse(c)
  942. unsigned char c;
  943. {
  944. static short ctemp1, cboff, ccount;
  945. static char cmode;
  946. static unsigned char ctlbuff[257];
  947.  
  948. if (cleft == 0) {
  949.     cmode = ccount = 0;
  950.     cleft = 12;
  951.     }
  952.  
  953. switch (cmode) {
  954.     case 0:            /* processing procedure header */
  955.         if (ccount == 8) ctemp1 = c;
  956.         if (ccount == 9) cleft = (ctemp1 << 8) + c + 3;
  957.         if (ccount == 11) {
  958.             cmode = 1;
  959.             ccount = 0;
  960.             }
  961.         else ccount++;
  962.         break;
  963.     case 1:            /* processing procedural instruction */
  964.         if (ccount == 0) {
  965.             cboff = 0;
  966.             ctlbuff[cboff++] = c;
  967.             if (c == 0x00) {
  968.                 exctl(ctlbuff, cboff);
  969.                 ccount = 0;
  970.                 }
  971.             else ccount++;
  972.             break;
  973.             }
  974.         ctlbuff[cboff++] = c;
  975.         if (ccount == 1) {
  976.             if ((ctlbuff[0] >= 0x08) && (ctlbuff[0] <= 0x0f)) {
  977.                 exctl(ctlbuff, cboff);
  978.                 ccount = 0;
  979.                 }
  980.             else {
  981.                 ctemp1 = c;        /* no. of operand bytes left */
  982.                 ccount++;
  983.                 }
  984.             break;
  985.             }
  986.         ccount++;
  987.         ctemp1--;
  988.         if (ctemp1 == 0) {
  989.             exctl(ctlbuff, cboff);
  990.             ccount = 0;
  991.             }
  992.         break;
  993.     default:
  994.         break;
  995.     }
  996. cleft--;
  997. }
  998.  
  999. exctl(opdata, len)            /* process control command */
  1000. unsigned char * opdata;
  1001. short len;
  1002. {
  1003. GrafPtr gp;
  1004. char setdflt;
  1005. short i;
  1006.  
  1007. GetPort(&gp);
  1008. if (PictPtr != 0) {
  1009.     SetPort(PictPtr);
  1010.     setgdev();
  1011.     }
  1012. else SetPort(myWindow);
  1013.  
  1014. if (cs.dblevel == 3) {            /* for level 3, dump all graphics */
  1015.     wsfdbg.grf_op = opdata[0];    /* temp */
  1016.     hexdump(opdata, len);        /* temp */
  1017.     }
  1018.  
  1019. switch(opdata[0]) {
  1020.     case 0x0a:                    /* erase graphics space */
  1021.         clrpict();
  1022.         break;
  1023.     case 0x00:                    /* no operation */
  1024.     case 0x01:                    /* comment */
  1025.     case 0x0f:                    /* stop draw */  /* no-op for 3179 */
  1026.         break;
  1027.     case 0x21:                    /* set current defaults */
  1028.                 /* untested- not used by test plots */
  1029.         setdflt = (opdata[5] & 0x80) == 0;
  1030.         switch(opdata[2]) {            /* SET code */
  1031.             case 0x00:                    /* drawing attributes */
  1032.                 i = 6;                        /* offset for next data byte */
  1033.                 if (opdata[3] & 0x80) {     /* color specified */
  1034.                     if (setdflt) dfltcolor = 4;        /* green */
  1035.                     else dfltcolor = opdata[i+1];
  1036.                     i += 2;
  1037.                     }
  1038.                 if (opdata[3] & 0x20) {        /* foreground mix specified */
  1039.                     if (setdflt) dfltmix = 2;        /* overpaint */
  1040.                     else dfltmix = opdata[i];
  1041.                     i++;
  1042.                     }    
  1043.                 break;
  1044.             case 0x01:                    /* line attributes */
  1045.                 i = 6;                        /* offset for next data byte */
  1046.                 if (opdata[3] & 0x80) {        /* line type specified */
  1047.                     if (setdflt) dfltlt = 7;    /* default is solid line */
  1048.                     else dfltlt = opdata[i];
  1049.                     i++;
  1050.                     }
  1051.                 if (opdata[3] & 0x40)        /* line width specified */
  1052.                     if (setdflt) dfltlw = 1;    /* default is 1 pixel wide */
  1053.                     else dfltlw = opdata[i];
  1054.                 break;
  1055.             case 0x02:                    /* character attributes */
  1056.                 break;                        /* not supported */
  1057.             case 0x03:                    /* marker attributes */
  1058.                 i = 6;                        /* offset for next data byte */
  1059.                 if (opdata[3] & 0x40)        /* cellsize */
  1060.                     i += 4;
  1061.                 if (opdata[3] & 0x10)        /* precision */
  1062.                     i += 1;
  1063.                 if (opdata[3] & 0x08)        /* symbol set */
  1064.                     i += 1;
  1065.                 if (opdata[3] & 0x01)        /* marker symbol */
  1066.                     if (setdflt) dfltmarker = 0xb5;        /* diamond */
  1067.                     else setmark(&dfltmarker, opdata[i]);
  1068.                 break;
  1069.             case 0x04:                    /* pattern attributes */
  1070.                 i = 6;                        /* offset for next data byte */
  1071.                 if (opdata[3] & 0x08)        /* symbol set */
  1072.                     i += 1;
  1073.                 if (opdata[3] & 0x01)        /* pattern symbol */
  1074.                     if (setdflt) setpat(dfltpat, 16);
  1075.                     else setpat(dfltpat, opdata[i]);
  1076.                 break;
  1077.             case 0x0b:                    /* arc parameters */
  1078.                 break;                        /* not supported */
  1079.             default:                    /* reserved; SAS & GDDM use 0x05, 0x07 */
  1080.                 if (cs.dblevel == 3) break;    /* for level 3, dumped already */        
  1081.                 wsfdbg.grf_op = opdata[0];        /* temp */
  1082.                 hexdump(opdata, len);            /* temp */
  1083.                 break;
  1084.             }
  1085.         break;
  1086.         /* no support for the graphics cursor */
  1087.     case 0x08:                    /* attach graphic cursor */
  1088.     case 0x09:                    /* detach graphic cursor */
  1089.     case 0x31:                    /* set graphic cursor pos. */
  1090.         break;
  1091.     default:
  1092.         if (cs.dblevel == 3) break;    /* for level 3, dumped already */        
  1093.         wsfdbg.grf_op = opdata[0];        /* temp */
  1094.         hexdump(opdata, len);            /* temp */
  1095.         break;
  1096.     }
  1097.  
  1098. if (PictPtr != 0) resetgdev();
  1099. SetPort(gp);
  1100. }
  1101.  
  1102. clrpict()        /* erase graphics space */
  1103. {
  1104. GrafPtr gp;
  1105. RGBColor rgbtemp;
  1106. static unsigned char endarea[] = {0x60, 0};
  1107. static unsigned char endimage[] = {0x93, 0};
  1108.  
  1109. pndclr = 0;                            /* reset pending clear */
  1110. if (drawpict == 0) return;            /* nothing to do if no graphics */
  1111. if (area_active) {                    /* end area if still active */
  1112.     exdraw(endarea, 2);                    /* execute end area command */
  1113.     }
  1114. if (image_active) {                    /* end image if still active */
  1115.     exdraw(endimage, 2);                /* execute end image command */
  1116.     }
  1117. if (pictopen) {                        /* close PICT file if open */
  1118.     closepictfile();
  1119.     }
  1120. GetPort(&gp);                        /* save current GrafPort */
  1121. if (PictPtr == 0) {                    /* erase port we draw in */
  1122.     SetPort(myWindow);
  1123.     EraseRect(&(myWindow->portRect));
  1124.     setmixmode(0);                    /* set default pen mode */
  1125.     }
  1126. else {
  1127.     SetPort(PictPtr);
  1128.     setgdev();
  1129.     EraseRect(&(PictPort.portRect));
  1130.     setmixmode(0);
  1131.     resetgdev();
  1132.     }
  1133. if (colormac) {
  1134.     SetPort(WritePtr);                /* restore background color */
  1135.     if (textmap) setgdev();
  1136.     GetEntryColor(myPalette, RGBback, &rgbtemp);
  1137.     RGBBackColor(&rgbtemp);
  1138.     if (textmap) resetgdev();
  1139.     }
  1140. SetPort(gp);                        /* restore GrafPort */
  1141. drawpict = 0;                        /* don't show graphics any more */
  1142. newpict = 1;                        /* next order starts new picture */
  1143. if (pendalign) {                    /* align bitmaps if changed during display */
  1144.     alignbitmaps();
  1145.     newstat();
  1146.     }
  1147. invldscr();                            /* force screen to be redrawn */
  1148.                                     /* end saving PICT file */
  1149. }
  1150.  
  1151. initpict()        /* initialize at start of new picture */
  1152. {
  1153. if (!newpict) return;
  1154. drawpict = 1;        /* clear initial screen */
  1155. clrpict();            /* (resets drawpict, sets newpict) */
  1156. newpict = 0;        /* no longer new picture */
  1157.                     /* begin saving PICT file */
  1158. if (savepict && (PictPtr != 0)) {
  1159.     openpictfile();
  1160.     }
  1161. }
  1162.  
  1163. showpict()        /* cause graphics data to be displayed */
  1164. {
  1165. GrafPtr gp;
  1166. RGBColor rgbtemp;
  1167.  
  1168. drawpict = 1;                        /* include graphics in screen updates */
  1169. if (colormac) {                        /* change text background to black or white */
  1170.     GetPort(&gp);
  1171.     SetPort(WritePtr);
  1172.     if (textmap) setgdev();
  1173.     if (cs.invertbw) GetEntryColor(myPalette, RGBwhite, &rgbtemp);
  1174.              else GetEntryColor(myPalette, RGBblack, &rgbtemp);
  1175.     RGBBackColor(&rgbtemp);
  1176.     SetPort(gp);
  1177.     if (textmap) resetgdev();
  1178.     }
  1179. invldscr();                            /* invalidate screen to force update */
  1180. }
  1181.  
  1182. /* The following two function are simple now, since Mac3270's response to
  1183.    WSF Query Reply now accurately describes the Mac screen dimensions.    
  1184.    Both SAS and GDDM adapt to this very well.                            */
  1185.  
  1186. sx(x)            /* convert data stream x-coordinate to Mac coordinate */
  1187. short x;
  1188. {
  1189. register short r;
  1190.  
  1191. /* if (PictPtr == 0) {
  1192.     if (cur_ptsize == 12) r = x + 286;
  1193.     else r = x + 246;
  1194.     }
  1195. else {
  1196.     if (cur_ptsize == 12) r = x + 318;
  1197.     else r = x + 255;
  1198.     }    */
  1199. r = x + hpixsize/2;
  1200. if (PictPtr == 0) {
  1201.     r += textRect.left;
  1202.     }
  1203. if (pictopen) {
  1204.     if (r < xmin) xmin = r;
  1205.     if (r > xmax) xmax = r;
  1206.     }
  1207. return(r);
  1208. }
  1209.  
  1210. sy(y)            /* convert data stream y-coordinate to Mac coordinate */
  1211. short y;
  1212. {
  1213. register short r;
  1214.  
  1215. /* if (PictPtr == 0) {
  1216.     if ((cur_ptsize == 9) && (cur_rows == 24)) r = 139 - y;
  1217.     else r = 188 - y;
  1218.     }
  1219. else {
  1220.     if ((cur_ptsize == 9) && (cur_rows == 24)) r = 146 - y;
  1221.     else r = 195 - y;
  1222.     } */
  1223.     
  1224. r = (vpixsize - 19)/2 - y;
  1225. if (PictPtr == 0) {
  1226.     r += textRect.top;
  1227.     }
  1228. if (pictopen) {
  1229.     if (r < ymin) ymin = r;
  1230.     if (r > ymax) ymax = r;
  1231.     }
  1232. return(r);
  1233. }
  1234.  
  1235. myLineTo(x, y)
  1236. short x, y;
  1237. {
  1238. switch (linet) {    /* set pen pattern for line type */
  1239.     case 8:                /* invisible */
  1240.             PenPat(qd.white);
  1241.             break;
  1242.     default:            /* all other, until I figure out how to do this */
  1243.             PenPat(qd.black);
  1244.             break;
  1245.     }
  1246.                     /* set pen width as requested */
  1247. if (linew == 0) PenSize(1, 1);
  1248. else PenSize(linew, linew);
  1249. LineTo(x, y);        /* draw the line */
  1250. PenPat(qd.black);    /* restore QuickDraw defaults */
  1251. PenSize(1, 1);
  1252. }
  1253.  
  1254. myDrawString(s)
  1255. unsigned char *s;            /* s is a Pascal string */
  1256. {
  1257. short i;
  1258. unsigned char xlstr[256];    /* translated copy of string */
  1259. Point penloc;
  1260. short texttop, textleft, textbottom, textright;
  1261. FontInfo fi;
  1262.  
  1263. if (s[0] == 0) return;        /* just return if null string */
  1264. xlstr[0] = s[0];            /* copy the string */
  1265. movmem(s+1, xlstr+1, s[0]);
  1266.  
  1267. if (nl_handle != 0) {
  1268.     for (i=1; i <= xlstr[0]; i++)        /* translate EBCDIC for language */
  1269.         xlstr[i] = nltab[xlstr[i]];
  1270.     }
  1271.  
  1272. if (pictopen && (xtabh != 0)) {
  1273.     for (i=1; i <= xlstr[0]; i++)        /* translate string to ASCII */
  1274.         xlstr[i] = (*xtabh)[xlstr[i]];
  1275.     }
  1276. ptoc(xlstr);
  1277. if (pictopen) {
  1278.     GetPen(&penloc);
  1279.     textleft = penloc.h;
  1280.     GetFontInfo(&fi);
  1281.     texttop = penloc.v + fi.ascent;
  1282.     textbottom = penloc.v - fi.descent - fi.leading;
  1283.     }
  1284. DrawString(xlstr);
  1285. if (pictopen) {
  1286.     GetPen(&penloc);
  1287.     textright = penloc.h;
  1288.     if (texttop > ymax) ymax = texttop;
  1289.     if (texttop < ymin) ymin = texttop;
  1290.     if (textbottom > ymax) ymax = textbottom;
  1291.     if (textbottom < ymin) ymin = textbottom;
  1292.     if (textleft < xmin) xmin = textleft;
  1293.     if (textleft > xmax) xmax = textleft;
  1294.     if (textright < xmin) xmin = textright;
  1295.     if (textright > xmax) xmax = textright;
  1296.     }
  1297. }
  1298.  
  1299. setrgb(newcolor, code)        /* set newcolor from data stream code */
  1300. short * newcolor;
  1301. unsigned char code;
  1302. {
  1303. if ((code == 0) || (code == 16)) code = dfltcolor;
  1304.  
  1305. switch(code) {
  1306.     case 1:                /* blue */
  1307.     case 9:                /* dark blue */
  1308.         (*newcolor) = RGBblue;
  1309.         break;
  1310.     case 2:                /* red */
  1311.     case 10:            /* orange */
  1312.         (*newcolor) = RGBred;
  1313.         break;
  1314.     case 3:                /* pink */
  1315.     case 11:            /* purple */
  1316.         (*newcolor) = RGBpink;
  1317.         break;
  1318.     case 4:                /* green */
  1319.     case 12:            /* dark green */
  1320.         (*newcolor) = RGBgreen;
  1321.         break;
  1322.     case 5:                /* turquoise */
  1323.     case 13:            /* dark turquoise */
  1324.         (*newcolor) = RGBturquoise;
  1325.         break;
  1326.     case 6:                /* yellow */
  1327.     case 14:            /* mustard */
  1328.         (*newcolor) = RGByellow;
  1329.         break;
  1330.     case 7:                /* neutral */
  1331.     case 15:            /* gray */
  1332.         if (cs.invertbw) (*newcolor) = RGBblack;
  1333.         else (*newcolor) = RGBwhite;
  1334.         break;
  1335.     case 8:                /* background */
  1336.         if (cs.invertbw) (*newcolor) = RGBwhite;
  1337.         else (*newcolor) = RGBblack;
  1338.         break;
  1339.     default:
  1340.         if (cs.invertbw) (*newcolor) = RGBblack;
  1341.         else (*newcolor) = RGBwhite;
  1342.         break;
  1343.     }
  1344. }
  1345.  
  1346. setmark(mark, code)        /* convert marker code to character */
  1347. unsigned char * mark, code;
  1348. {
  1349. unsigned char markchar;
  1350.  
  1351. switch(code) {
  1352.     case 0x00:            /* default */
  1353.         markchar = dfltmarker;
  1354.         break;
  1355.     case 0x01:            /* cross */
  1356.         markchar = 0x46;    /* sort of a cross */
  1357.         break;
  1358.     case 0x02:            /* plus */
  1359.         markchar = 0x4e;    /* normal plus */
  1360.         break;
  1361.     case 0x05:            /* 6-point star */
  1362.     case 0x06:            /* 8-point star */
  1363.         markchar = 0x5c;    /* normal asterisk */
  1364.         break;
  1365.     default:
  1366.         markchar = 0xb5;    /* solid diamond */
  1367.         break;
  1368.     }
  1369. (*mark) = markchar;        /* return result */
  1370. }
  1371.  
  1372. setpat(pat, code)        /* define pattern from code */
  1373. unsigned char * pat, code;
  1374. {
  1375. static Pattern pattab[16] = {
  1376.     {0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff},    /* 87.5% gray */
  1377.     {0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77},    /* 75% gray */
  1378.     {0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55},    /* 50% gray */
  1379.     {0xaa, 0x00, 0x55, 0x00, 0xaa, 0x00, 0x55, 0x00},    /* 25% gray */
  1380.     {0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00},    /* 12.5% gray */
  1381.     {0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00},    /* 6.25% gray */
  1382.     {0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00},    /* 3.125% gray */
  1383.     {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},    /* 1.5625% gray */
  1384.     {0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88},    /* vertical lines */
  1385.     {0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00},    /* horizontal lines */
  1386.     {0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88},    /* "/" diags, less steep */
  1387.     {0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88},    /* "/" diags., 45 degrees */
  1388.     {0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11},    /* "\" diags., less steep */
  1389.     {0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11},    /* "\" diags., 45 degrees */
  1390.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},    /* white (none) */
  1391.     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};    /* black (solid) */    
  1392.  
  1393. if (code == 0) movmem(dfltpat, pat, 8);
  1394. else {
  1395.     if (code > 16) code = 16;
  1396.     movmem(pattab[code-1], pat, 8);
  1397.     }
  1398. }
  1399.  
  1400. setmixmode(mode)
  1401. short mode;
  1402. {
  1403. if (mode == 0) mode = dfltmix;
  1404. switch(mode) {
  1405.     case 1:                /* "mix" colors */
  1406.             if (colormac) {
  1407.                 if (cs.invertbw) {
  1408.                     PenMode(adMin);
  1409.                     copymode = adMin;
  1410.                     }
  1411.                 else {
  1412.                     PenMode(adMax);
  1413.                     copymode = adMax;
  1414.                     }
  1415.                 }
  1416.             else {
  1417.                 PenMode(patOr);
  1418.                 copymode = srcOr;
  1419.                 }
  1420.             break;
  1421.     default:            /* overpaint */
  1422.             PenMode(patCopy);
  1423.             copymode = srcCopy;
  1424.             break;
  1425.     }
  1426. }
  1427.  
  1428. openpictfile()
  1429. {
  1430. Point where;
  1431. ProcPtr dlgHook;
  1432. SFReply reply;
  1433. OSErr rc;
  1434. short i;
  1435. long longzero = 0;
  1436. long iocount;
  1437. GrafPtr gp;
  1438.  
  1439. where = sfppoint;
  1440. dlgHook = 0;
  1441. arrowcursor();
  1442. SFPutFile(&where, "Save graphics in:",
  1443.           pict_fName, dlgHook, &reply);
  1444. if (reply.good == 0) return;
  1445. ptoc(&reply.fName);
  1446. movmem(&reply.fName, pict_fName, 64);        /* save filename */
  1447. rc = FSDelete(&reply.fName, reply.vRefNum);    /* delete existing file */
  1448. if ((rc != 0) && (rc != -43)) {        /* file not found is ok */
  1449.     stoperr(wpictalrt);
  1450.     return;
  1451.     }
  1452. rc = Create(&reply.fName, reply.vRefNum, 'MDRW', 'PICT');
  1453. if (rc != 0) {
  1454.     stoperr(wpictalrt);
  1455.     return;
  1456.     }
  1457. rc = FSOpen(&reply.fName, reply.vRefNum, &pictfref);
  1458. if (rc != 0) {
  1459.     stoperr(wpictalrt);
  1460.     return;
  1461.     }
  1462.                                 /* write 512-byte header */
  1463. for (i=0; i < 512/4; i++) {
  1464.     iocount = 4;
  1465.     rc = FSWrite(pictfref, &iocount, &longzero);
  1466.     if (rc != 0) break;
  1467.     }
  1468.                                 /* write fixed fields of PICT */
  1469. if (rc == 0) {
  1470.     for (i=0; i < (sizeof(short) + sizeof(Rect))/2; i++) {
  1471.         iocount = 2;
  1472.         rc = FSWrite(pictfref, &iocount, &longzero);
  1473.         if (rc != 0) break;
  1474.         }
  1475.     }
  1476.     
  1477. if (rc != 0) {                    /* clean up if write error */
  1478.     FSClose(pictfref);
  1479.     FSDelete(&reply.fName, reply.vRefNum);
  1480.     stoperr(wpictalrt);
  1481.     return;
  1482.     }
  1483. pictvref = reply.vRefNum;
  1484. pictopen = 1;
  1485. picterr = 0;
  1486. xmin = ymin = 0x7fff;
  1487. xmax = ymax = 0x8000;
  1488. if (colormac) SetStdCProcs(&myProcs);
  1489. else SetStdProcs(&myProcs);
  1490. PictPtr->grafProcs = &myProcs;
  1491. myProcs.putPicProc = myStdPutPic;
  1492. GetPort(&gp);
  1493. SetPort(PictPtr);
  1494. TextFont(4);
  1495. picthandle = (Ptr)0L;
  1496. picthandle = OpenPicture(&PictPtr->portRect);
  1497. ShowPen();
  1498. PicComment(picDwgBeg, 0, 0L);        /* start MacDraw Picture */
  1499. PicComment(picGrpBeg, 0, 0L);        /* begin a group */
  1500. theWidth = NewHandle((Size)sizeof(Point));
  1501. if (theWidth != 0) {
  1502.     ((Point *)(*theWidth))->v = 1;
  1503.     ((Point *)(*theWidth))->h = 3;        /* use 1/3 normal width */
  1504.     PicComment(SetLineWidth, sizeof(Point), theWidth);    /* set new line width */
  1505.     }
  1506. pictcount = sizeof(Picture);
  1507. SetPort(gp);
  1508. }
  1509.  
  1510. closepictfile()
  1511. {
  1512. OSErr rc;
  1513. GrafPtr gp;
  1514. long iocount, pictpos;
  1515. struct pictfixed {
  1516.     short    pictlen;
  1517.     Rect    pictrect;
  1518.     } pf;
  1519.  
  1520. GetPort(&gp);
  1521. SetPort(PictPtr);
  1522. PicComment(picGrpEnd, 0, 0L);        /* end a group */
  1523. PicComment(picDwgEnd, 0, 0L);        /* end MacDraw Picture */
  1524. HidePen();
  1525. ClosePicture();
  1526. TextFont(stdfont);
  1527.  
  1528. /* save the current file position */
  1529. if (picterr == 0) {
  1530.     picterr = GetFPos(pictfref, &pictpos);
  1531.     }
  1532.     
  1533. /* set position after MacDraw header */
  1534. if (picterr == 0) {
  1535.     picterr = SetFPos(pictfref, fsFromStart, (long)512);
  1536.     }
  1537.  
  1538. /* copy fixed picture fields */
  1539. movmem((Ptr)(*picthandle), &pf, sizeof(struct pictfixed));
  1540. /* adjust rectangle to match actual plot */
  1541. pf.pictrect.top = ymin;
  1542. pf.pictrect.left = xmin;
  1543. pf.pictrect.bottom = ymax;
  1544. pf.pictrect.right = xmax;
  1545.  
  1546. /* write the final fixed picture fields */
  1547. if (picterr == 0) {
  1548.     iocount = sizeof(struct pictfixed);
  1549.     picterr = FSWrite(pictfref, &iocount, &pf);
  1550.     }
  1551.  
  1552. /* reset the file position to the end */
  1553. if (picterr == 0) {
  1554.     picterr = SetFPos(pictfref, fsFromStart, pictpos);
  1555.     }
  1556.     
  1557. KillPicture(picthandle);
  1558. SetPort(gp);
  1559. PictPtr->grafProcs = (Ptr)0L;
  1560. rc = FSClose(pictfref);
  1561. if (theWidth != 0) {
  1562.     DisposHandle(theWidth);
  1563.     }
  1564. pictopen = 0;
  1565. if ((rc != 0) || (picterr != 0)) {
  1566.     stoperr(wpictalrt);
  1567.     FSDelete(pict_fName, pictvref);
  1568.     }
  1569. }
  1570.  
  1571. pascal void myStdPutPic(dataPtr, byteCount)
  1572. Ptr dataPtr;
  1573. unsigned short byteCount;
  1574. {
  1575. long iocount;
  1576.  
  1577. if (picterr != 0) return;
  1578. iocount = byteCount;
  1579. pictcount += byteCount;
  1580. picterr = FSWrite(pictfref, &iocount, dataPtr);
  1581. if (picthandle != 0) (*picthandle)->picSize = pictcount;
  1582. }
  1583.  
  1584. hexdump(data, len)                /*temp*/
  1585. unsigned char * data;
  1586. short len;
  1587. {
  1588. short count, i;
  1589. FILE * fp;
  1590. static char openflg = 0;
  1591.  
  1592. if (!cs.dblevel) return;
  1593.  
  1594. if (openflg == 0) {
  1595.     fp = fopen("Ram:wsfdebug", "w");
  1596.     if (fp == 0) return;
  1597.     openflg = 1;
  1598.     }
  1599. else {
  1600.     fp = fopen("Ram:wsfdebug", "a");
  1601.     if (fp == 0) return;
  1602.     }
  1603. fprintf(fp, "wsf_op = %x, wsf_gr = %x, grf_op = %x, length = %d\n",
  1604.     wsfdbg.wsf_op, wsfdbg.wsf_gr, wsfdbg.grf_op, len);
  1605.  
  1606. count = 0;
  1607. for (i=0; i < len; i++) {
  1608.     fprintf(fp, "%02x", data[i]);
  1609.     count++;
  1610.     if (count == 32) {
  1611.         fprintf(fp, "\n");
  1612.         count = 0;
  1613.         }
  1614.     }
  1615. if (count != 0) fprintf(fp, "\n");
  1616. fprintf(fp, "\n");
  1617. fclose(fp);
  1618. }
  1619.